package com.util.textProcess;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;

public class Calculate_Vector_Similarity {

	// 定义推荐的信息数
	private static int recommend_num = 30;

	static ConnectionPool pool = ConnectionPool.getInstance();
	static Connection conn = (Connection) pool.getConnection();
	static PreparedStatement stmt;

	/**
	 * 读取用户兴趣模型向量
	 * 
	 * @param args
	 * @throws SQLException
	 */
	public static LinkedHashMap<String, Double> getInterestVector(int userid)
			throws SQLException {
		String sql = "SELECT * FROM interestInfo where userId=?";
		stmt = (PreparedStatement) conn.prepareStatement(sql);
		stmt.setInt(1, userid);
		ResultSet rs = stmt.executeQuery();
		LinkedHashMap<String, Double> map = new LinkedHashMap<String, Double>();
		while (rs.next()) {
			short isChannel = 1;
			isChannel = rs.getShort("isChannel");
			Double decay_weight = 1.0d;
			// 如果是隐式获取的兴趣特征项，则利用衰减函数进行权值衰减
			if (isChannel == 0) {
				Timestamp modifyTime = rs.getTimestamp("modifyTime");
				// 得出衰减的倍数
				decay_weight = DecayFunc.getDecayWeight(modifyTime);
				System.out.println("权值衰减为原来的" + decay_weight);
			}

			String interestName = rs.getString("interestName");
			Double interestWeight = rs.getDouble("interestWeight");
			map.put(interestName, interestWeight * decay_weight);
		}
		return map;
	}

	private static Double calculateSim(LinkedHashMap<String, Double> first,
			LinkedHashMap<String, Double> second) {
		// TODO Auto-generated method stub
		// 计算相似度
		double vectorFirstModulo = 0.00;// 向量1的模
		double vectorSecondModulo = 0.00;// 向量2的模
		double vectorProduct = 0.00; // 向量积

		for (String first_key : first.keySet()) {
			for (String second_key : second.keySet()) {
				if (first_key.equals(second_key)) {
					vectorProduct += first.get(first_key).doubleValue()
							* second.get(second_key).doubleValue();
				}
				vectorSecondModulo += second.get(second_key).doubleValue()
						* second.get(second_key).doubleValue();
			}
			vectorFirstModulo += first.get(first_key).doubleValue()
					* first.get(first_key).doubleValue();
		}
		return vectorProduct
				/ (Math.sqrt(vectorFirstModulo) * Math.sqrt(vectorSecondModulo));
	}

	// public static void main(String[] args) throws SQLException, IOException {
	public static ArrayList<Long> getRecommendFileIDList(int userid)
			throws SQLException, IOException {
		// TODO Auto-generated method stub
		TreeMap<Long, Double> treemap = new TreeMap<Long, Double>();
		LinkedHashMap<String, Double> interestVector = getInterestVector(userid);
		HashMap<Long, LinkedHashMap<String, Double>> docsVector = TfIdfAlgorithm
				.getDocVector();
		Set<Long> fileId = docsVector.keySet();
		for (Long id : fileId) {
			Double similarity = 0d;
			if (!interestVector.isEmpty() && !docsVector.get(id).isEmpty()) {
				LinkedHashMap<String, Double> docVector = TfIdfAlgorithm.docsVector
						.get(id);
				similarity = calculateSim(docVector, interestVector);
			} else {
				similarity = 0d;
			}
			treemap.put(id, similarity);
		}
		List<Map.Entry<Long, Double>> list = new ArrayList<Map.Entry<Long, Double>>(
				treemap.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<Long, Double>>() {
			// 降序排序
			public int compare(Entry<Long, Double> o1, Entry<Long, Double> o2) {
				return o2.getValue().compareTo(o1.getValue());
			}
		});
		System.out.print("该用户的兴趣向量模型为：{");
		Set<String> interest_keySet = interestVector.keySet();
		for (String interest : interest_keySet) {
			System.out.print("(" + interest + ","
					+ interestVector.get(interest) + ")");
		}
		System.out.println("}");

		// System.out.println("与当前用户兴趣最匹配的30篇文档列表如下：");
		ArrayList<Long> tempList = new ArrayList<Long>();
		for (Map.Entry<Long, Double> entry : list) {
			tempList.add(entry.getKey());
		}
		ArrayList<Long> fileIdList = new ArrayList<Long>();
		for (int i = 0; i < recommend_num; i++) {
			fileIdList.add(tempList.get(i));
		}
		return fileIdList;
	}

}
